package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.bean.Category;
import com.itheima.bean.Dish;
import com.itheima.bean.Setmeal;
import com.itheima.bean.SetmealDish;
import com.itheima.dao.CategoryDao;
import com.itheima.dao.DishDao;
import com.itheima.dao.SetmealDao;
import com.itheima.dao.SetmealDishDao;
import com.itheima.dto.SetmealDto;
import com.itheima.exception.CustomException;
import com.itheima.service.SetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealDao, Setmeal> implements SetmealService {

    @Autowired
    private SetmealDao setmealDao;

    @Autowired
    private SetmealDishDao setmealDishDao;

    @Autowired
    private CategoryDao categoryDao;

    @Autowired
    private DishDao dishDao;

    /**
     * 保存套餐及其包含菜品信息
     * @param setmealDto
     */
    @Transactional
    @Override
    public void saveWithDish(SetmealDto setmealDto) {
        //1.判断套餐名称是否已经存在 存在：抛出异常提示
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Setmeal::getName,setmealDto.getName());
        Integer count = setmealDao.selectCount(wrapper);
        if(count>0){
            throw new CustomException(0,"套餐名称'"+setmealDto.getName()+"'已经存在");
        }

        //2.保存套餐基本信息到setmeal表中
        setmealDao.insert(setmealDto);

        //获取当前新增套餐id
        Long setmealId = setmealDto.getId();

        //3.保存套餐包含的菜品信息到setmeal_dish表中
        //3.0：获取当前套餐下包含的菜品列表数据
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes.stream().forEach(setmealDish -> {
            //3.1：设置每个菜品关联当前套餐id
            setmealDish.setSetmealId(setmealId);
            //3.2：保存菜品到套餐菜品表中
            setmealDishDao.insert(setmealDish);
        });
    }

    /**
     * 分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public Page<SetmealDto> findPage(Integer page, Integer pageSize, String name) {
        //1.创建Page对象封装分页参数page和pageSize
        Page<Setmeal> setmealPage = new Page<>(page, pageSize);

        //2.创建wrapper对象封装查询条件name 根据套餐名称模糊查询
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(name!=null&&name.length()>0,Setmeal::getName,name);

        //3.调用selectPage()方法对setmeal表进行分页查询 Page<Setmeal>
        setmealDao.selectPage(setmealPage,wrapper);

        //4.将Page<Setmeal>中的当前页数据和总条数封装到Page<SetmealDto>对象
        Page<SetmealDto> setmealDtoPage = new Page<>();


        //4.0：获取setmealPage对象中包含的当前页数据集合 List<Setmeal> setmealList
        List<Setmeal> setmealList = setmealPage.getRecords();

        //4.1：将前面查询的当前页数据List<Setmeal>封装到List<SetmealDto>
        List<SetmealDto> setmealDtoList = setmealList.stream().map(setmeal -> {
            //a:创建setmealDto对象
            SetmealDto setmealDto = new SetmealDto();
            //b:使用工具类将setmeal对象中的数据复制到setmealDto对象中
            BeanUtils.copyProperties(setmeal,setmealDto);
            //c：为setmealDto中的categoryName属性赋值  根据套餐所属的category_id去category分类表中查询得到分类信息
            Category category = categoryDao.selectById(setmeal.getCategoryId());
            setmealDto.setCategoryName(category!=null?category.getName():"未知");
            //d：返回setmealDto对象
            return setmealDto;
        }).collect(Collectors.toList());

        setmealDtoPage.setRecords(setmealDtoList);//设置当前页显示的数据列表

        //4.2：将Page<Setmeal>中的总条数total封装到Page<SetmealDto>对象中
        setmealDtoPage.setTotal(setmealPage.getTotal());//设置总条数

        //5.返回Page<SetmealDto>对象
        return setmealDtoPage;
    }

    /**
     * 单个删除|批量删除
     * 优化：
     *  优化1：提示具体哪个套餐处于启售状态
     *  优化2：使用逻辑删除
     *      1.数据库表添加逻辑删除字段                          is_deleted
     *      2.实体类添加逻辑删除字段对应属性                     isDeleted
     *      3.在application.yml配置文件中全局配置逻辑删除
     * @param ids
     */
    @Transactional
    @Override
    public void deleteByIds(List<Long> ids) {
        //1.判断ids中是否为null  提示：没有选中要删除的套餐
        if(ids==null || ids.size()==0){
            throw new CustomException(0,"没有选中要删除的套餐!");
        }

        //2.判断要删除的套餐是否处于停售状态  如果处于起售状态：则不能删除 抛出异常提示
        //根据要删除的套餐id  设置查询条件status=1 进行统计 如果个数大于1，说明存在启售状态的套餐，不能删除
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Setmeal::getId,ids);
        List<Setmeal> setmealList = setmealDao.selectList(wrapper);
        for (Setmeal setmeal : setmealList) {
            if(setmeal.getStatus()==1){
                throw new CustomException(0,"当前套餐'"+setmeal.getName()+"'处于启售状态，无法删除！");
            }
        }

        //3.根据id删除指定套餐 setmeal
        wrapper.eq(Setmeal::getStatus,0);        //status=0
        setmealDao.delete(wrapper);                // delete from setmeal where id in () and status=1

        //4.根据套餐id去setmeal_dish表中删除指定套餐下包含的菜品信息
        LambdaQueryWrapper<SetmealDish> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(SetmealDish::getSetmealId,ids);
        setmealDishDao.delete(wrapper2);        // delete from setmeal_dish where setmeal_id in ()
    }

    @Override
    public SetmealDto selectByid(Long id) {

        Setmeal setmeal = setmealDao.selectById(id);

        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal, setmealDto);

        LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetmealDish::getSetmealId, setmeal.getId());
        List<SetmealDish> list = setmealDishDao.selectList(wrapper);
        setmealDto.setSetmealDishes(list);


        return setmealDto;
    }

    @Override
    public void updateSetmeal(SetmealDto setmealDto) {
//        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(Setmeal::getName,setmealDto.getName());
//        wrapper.ne(Setmeal::getId,setmealDto.getId());
//        Integer count = setmealDao.selectCount(wrapper);
//        if (count > 0) {
//            throw new CustomException(0,"套餐名称'" + setmealDto.getName() + "'已存在!");
//        }
//
//        setmealDao.updateById(setmealDto);
        this.updateById(setmealDto);
//        清理当前setmeadishn的数据
        LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());

        setmealDishDao.delete(wrapper);
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        for (SetmealDish setmealDish : setmealDishes) {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDishDao.insert(setmealDish);
        }



    }





    /*@Transactional
    @Override
    public void deleteByIds(List<Long> ids) {
        //1.判断ids中是否为null  提示：没有选中要删除的套餐
        if(ids==null || ids.size()==0){
            throw new CustomException(0,"没有选中要删除的套餐!");
        }

        //2.判断要删除的套餐是否处于停售状态  如果处于起售状态：则不能删除 抛出异常提示
        //根据要删除的套餐id  设置查询条件status=1 进行统计 如果个数大于1，说明存在启售状态的套餐，不能删除
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Setmeal::getId,ids);
        wrapper.eq(Setmeal::getStatus,1);       //status=1
        Integer count = setmealDao.selectCount(wrapper);
        if(count>0){
            throw new CustomException(0,"当前存在套餐处于启售状态，无法删除！");
        }

        //3.根据id删除指定套餐 setmeal
        LambdaQueryWrapper<Setmeal> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(Setmeal::getId,ids);
        wrapper1.eq(Setmeal::getStatus,0);        //status=0
        setmealDao.delete(wrapper1);                // delete from setmeal where id in () and status=1

        //4.根据套餐id去setmeal_dish表中删除指定套餐下包含的菜品信息
        LambdaQueryWrapper<SetmealDish> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(SetmealDish::getSetmealId,ids);
        setmealDishDao.delete(wrapper2);        // delete from setmeal_dish where setmeal_id in ()
    }*/
}
